package com.csw.compose.ui.module.state

import android.annotation.SuppressLint
import androidx.compose.animation.animateColor
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.csw.compose.theme.pagePadding
import com.csw.compose.ui.Destination
import com.csw.compose.ui.components.BodyText
import com.csw.compose.ui.components.LabelText
import com.csw.compose.ui.components.LargeSpacer
import com.csw.compose.ui.components.NormalSpacer
import com.csw.compose.ui.components.OlItem
import com.csw.compose.ui.components.PrimaryTitle
import com.csw.compose.ui.components.UlItem
import com.csw.compose.ui.module.BasePage
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch

@Preview
@Composable
fun EffectPagePreview() {
    BasePage({}, "附带效应（Effect）") {
        EffectPage()
    }
}

class EffectPageData {
    companion object : Destination("EffectPage")
}

@Composable
fun EffectPage() {
    Column(
        modifier = Modifier
            .padding(horizontal = pagePadding)
            .verticalScroll(rememberScrollState())
    ) {
        PrimaryTitle("简介")
        BodyText("同样由于组合函数的特殊性（重组、生命周期），我们常常需要在组件显示时执行一些异步任务，而这些任务又常常需要在组件被移除时停止，附带效应就是跟组件的生命周期相关的异步任务api")
        NormalSpacer()

        CoroutineScopeExample()
        UlItem("协程")
        LabelText("通过协程实现异步任务，会因为重组重复触发，又因为组件没有移除，协程没有及时停止")

        LargeSpacer()
        LaunchedEffectExample()
        UlItem("LaunchedEffect")
        LabelText("启动附带效应，在该组合加载时，执行协程")
        OlItem(1, "key")
        LabelText("用于控制是否重启附带效应，当传入的变量发生更改时，会再次启动附带效应")

        LargeSpacer()
        DisposableEffectExample()
        UlItem("DisposableEffect")
        LabelText("一次性附带效应，在组合加载时执行并提供onDispose方法用于告知组件卸载，一般用于事件监听之类的行为，在组件移除时取消监听")

        LargeSpacer()
        val color by rememberInfiniteTransition("color").animateColor(
            Color.Green, Color.Blue,
            infiniteRepeatable(tween(1000), repeatMode = RepeatMode.Reverse)
        )
        SideEffectExample(color)
        UlItem("SideEffect")
        LabelText("侧载附带效应，每一次组合重组都会执行")

    }
}

@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun CoroutineScopeExample() {
    var times by remember { mutableIntStateOf(0) }
    val scope = rememberCoroutineScope()
    scope.launch {
        while (isActive) {
            delay(1000)
            times++
        }
    }
    Text("计时：${times}")
}


@Composable
fun LaunchedEffectExample() {
    var times by remember { mutableIntStateOf(0) }
    LaunchedEffect(Unit) {
        while (isActive) {
            delay(1000)
            times++
        }
    }
    Text("计时：${times}")
}

@Composable
fun DisposableEffectExample() {
    var times by remember { mutableIntStateOf(0) }
    DisposableEffect(Unit) {
        times++
        onDispose {
            times = 0
        }
    }
    Text("计时：${times}")
}

@Composable
fun SideEffectExample(color: Color) {
    var times by remember { mutableIntStateOf(0) }
    SideEffect {
        times++
    }
    Text("重组次数：${times}", color = color)
}
